package com.hengpeng.itfin.service.repayment.impl;

import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.hibernate.annotations.common.util.StringHelper;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.hengpeng.common.exception.ServiceResult;
import com.hengpeng.common.exception.ServiceResultFactory;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.persist.query.Projections;
import com.hengpeng.common.persist.query.constants.QueryConstants.QueryType;
import com.hengpeng.common.util.DateTimeUtil;
import com.hengpeng.common.util.MoneyUtil;
import com.hengpeng.itfin.constants.MSConstants;
import com.hengpeng.itfin.service.impl.BaseServiceImpl;
import com.hengpeng.itfin.service.repayment.RepaymentService;
import com.hengpeng.itfin.tools.New;
import com.hengpeng.itfin.tools.PoolServer;
import com.hengpeng.itfinbase.constants.RespCodeConstants;
import com.hengpeng.itfinbase.constants.RespCodeConstants.CommonCode;
import com.hengpeng.itfinbase.constants.TransCodeConstants;
import com.hengpeng.itfinbase.message.partner.PartnerTransType;
import com.hengpeng.itfinbase.message.partner.ReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.ReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.ReconciliationResponseMsg.ReconciliationInfo;
import com.hengpeng.itfinbase.message.partner.RepaymentRequestMsg;
import com.hengpeng.itfinbase.message.partner.RepaymentResponseMsg;
import com.hengpeng.itfinbase.message.partner.RepaymentResponseMsg.RepaymentResponseErrorMsg;
import com.hengpeng.itfinbase.message.partner.TransferResponse;
import com.hengpeng.itfinbase.message.partner.TrfReconciliationRequestMsg;
import com.hengpeng.itfinbase.message.partner.TrfReconciliationResponseMsg;
import com.hengpeng.itfinbase.message.partner.TrfReconciliationResponseMsg.TrfReconciliationDto;
import com.hengpeng.itfinbase.persist.Account;
import com.hengpeng.itfinbase.persist.AccountLog.TradeMode;
import com.hengpeng.itfinbase.persist.AccountLog.TransType;
import com.hengpeng.itfinbase.persist.BorrowInfo;
import com.hengpeng.itfinbase.persist.BorrowInfo.BorrowStatus;
import com.hengpeng.itfinbase.persist.InvestInfo;
import com.hengpeng.itfinbase.persist.InvestInfo.InvestStatus;
import com.hengpeng.itfinbase.persist.ReceivePlan;
import com.hengpeng.itfinbase.persist.ReceivePlan.ReceiveStatus;
import com.hengpeng.itfinbase.persist.RecoverRepay;
import com.hengpeng.itfinbase.persist.RecoverRepay.RecoverRepayStatus;
import com.hengpeng.itfinbase.persist.RepaymentPlan;
import com.hengpeng.itfinbase.persist.RepaymentPlan.ReplaymentStatus;
import com.hengpeng.itfinbase.persist.RepaymentPlan.ReplaymentType;

@Lazy
@Service
@Transactional
public class RepaymentServiceImpl extends BaseServiceImpl implements RepaymentService {
	
	private final static ExecutorService execute = Executors.newCachedThreadPool();
	
	@Override
	public boolean checkRepaymentPlanIsRepaymented(Long borrowInfoId, Integer curRecNum) {
		DynamicQuery query = new DynamicQuery(ReceivePlan.class);
		query.addProjection(Projections.count());
		if (borrowInfoId != null) {
			query.eq("borrowInfoId", borrowInfoId);
		}
		if (curRecNum != null) {
			query.eq("curRecNum", curRecNum);
		}
		query.inArray("status", new ReceiveStatus[]{ReceiveStatus.WAITREC,ReceiveStatus.RECEIVING} );
		query.setQueryType(QueryType.JDBC);
		Long size = serviceFactory.getDaoFactory().getReceivePlanDao().countByDynamicQuery(query);
		return size > 0  ? false : true;
	}

	@Override
	public boolean checkBorrowInfoIsRepaymented(Long borrowInfoId) {
		DynamicQuery query = new DynamicQuery(RepaymentPlan.class);
		query.addProjection(Projections.count());
		if (borrowInfoId != null) {
			query.eq("borrowinfoId", borrowInfoId);
		}
		query.inArray("status", new ReplaymentStatus[] { ReplaymentStatus.UNSETTLE, ReplaymentStatus.SETTLING });
		query.setQueryType(QueryType.JDBC);
		Long size = serviceFactory.getDaoFactory().getRepaymentPlanDao().countByDynamicQuery(query);
		return size > 0  ? false : true;
	}
	
	
	/**
	 * <pre>
	 * 程序执行步骤：
	 * 一,对于返回的结果中成功的部分执行如下操作：
				(1)更新对应的收款计划中收款状态为：已收款 
				(2)生成还款人的还款资金流水,资金流水中的金额就是成功部分的金额总计. 
				(3)生成收款人的收款资金流水
	 * 		    (4)更新借款人资金账户表中可用余额,待还本金,待还利息字段信息,更新收款人资金账户表中可用余额,累计收益金额,待收本金,待收收益字段信息。 
	 * 二,成功的部分执行完成之后,判断本期还款计划对应的收款计划是否已经都还清,如果都还清则更新本期还款计划状态为：已还清。
	 * 三,步骤二执行完成之后,判断借款人的所有还款计划是否已经全部还清，若已经全部还清则更新借款标的状态为：已还清。
	 * 四,当还款为平台垫资还款时需生成追偿信息表
	 * </pre>
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public ServiceResult<String> dealBatchRepaymentResult(RepaymentResponseMsg response) {
		String batchId = response.getBatchId();// 还款批次id
		String proId = response.getProId();// 借款标的id
		BorrowInfo borrowInfo = daoFactory.getBorrowInfoDao().get(Long.parseLong(proId));// 获取标的信息
		if (borrowInfo == null || borrowInfo.getStatus() != BorrowInfo.BorrowStatus.REPAYMENTING) {
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_FAIL, null, "标的信息不存在或状态异常");
		}
		
		RepaymentPlan repaymentPlan = daoFactory.getRepaymentPlanDao().get(response.getRepaymentPlanId());
		if (!ReplaymentStatus.UNSETTLE.equals(repaymentPlan.getStatus()) && !ReplaymentStatus.SETTLING.equals(repaymentPlan.getStatus())) {
			return ServiceResultFactory.getServiceResult(RespCodeConstants.CommonCode.TRANS_FAIL, null, "该笔还款计划已经还完:" + response.getRepaymentPlanId());
		}
		
		List<String> errorIds = New.list();// 执行失败的还款订单号
		List<RepaymentResponseErrorMsg> errorMsg = response.getRepaymentErrorMsg();
		if (errorMsg != null && errorMsg.size() > 0) {
			for (RepaymentResponseErrorMsg m : errorMsg) {
				errorIds.add(m.getOrdId());
			}
		}
		Long repayMoney = 0L;// 借款人应还金额
		Long recInterestMoney = 0L; //借款人应还利息
		Long base = 0L;//借款人应还本金
		Integer curRecNum = null;// 本批次处理的还款计划期数
		List<ReceivePlan> receivePlans = daoFactory.getReceivePlanDao().getRepayReceivePlans(Long.parseLong(proId), batchId,null, new ReceiveStatus[] { ReceiveStatus.RECEIVING });
		for (ReceivePlan rp : receivePlans) {
			curRecNum = rp.getCurRecNum();
			if (!errorIds.contains(String.valueOf(rp.getId()))) {// 只对成功的记录进行操作
				int i = serviceFactory.getDaoFactory().getReceivePlanDao().updateStatus(rp.getId(), ReceiveStatus.RECEIVED, ReceiveStatus.RECEIVING, new Date(),new Date());
				if (i > 0) {
					InvestInfo investInfo = serviceFactory.getDaoFactory().getInvestInfoDao().get(rp.getInvestmentInfoId());
					
					// 收款人资金账户变动,资金流水添加
					serviceFactory.getAccountService().changeAccountMoney(investInfo.getNowOwnUserId(),
							rp.getRecBaseMoney(), rp.getRecBaseMoney(), 0L, TransType.REPAYMENT, TradeMode.ADD,
							rp.getId().toString(), "收回本金 | 投资：" + borrowInfo.getBorrowName());

					// 收款人资金账户变动,资金流水添加 回收利息
					serviceFactory.getAccountService().changeAccountMoney(investInfo.getNowOwnUserId(),
							rp.getRecInterestMoney(), 0L, rp.getRecInterestMoney(), TransType.REPAYMENT,
							TradeMode.ADD, rp.getId().toString(), "收回利息 | 投资：" + borrowInfo.getBorrowName());

					// 收款人资金账户变动,资金流水添加,附加利息
					if (rp.getRecAddMoney() > 0) {
						serviceFactory.getAccountService().changeAccountMoney(investInfo.getNowOwnUserId(),
								rp.getRecAddMoney(), 0L, rp.getRecAddMoney(), TransType.ADDMONEY, TradeMode.ADD,
								rp.getId().toString(), "收回附加利息 | 投资：" + borrowInfo.getBorrowName());
					}

					repayMoney = repayMoney + rp.getRecBaseMoney() + rp.getRecInterestMoney() + rp.getRecAddMoney();
					recInterestMoney = recInterestMoney + rp.getRecInterestMoney();
					base = base + rp.getRecBaseMoney();
				}
			}
		}
		// 还款人资金账户变动,资金流水添加
		if (repayMoney > 0) {
			if (MSConstants.CHAR_ONE.equals(response.getMerPriv())) {// 担保公司垫资还款,记录担保用户账户资金变动
				serviceFactory.getAccountService().changeAccountMoney(borrowInfo.getGuaranteeUserId(), repayMoney,
						TransType.ADVANCEREPAY, TradeMode.SUBTRACT, borrowInfo.getId().toString(),
						"担保人垫资本息| 标的:" + borrowInfo.getBorrowName());
			} else {// 借款人正常还款
				serviceFactory.getAccountService().changeAccountMoney(borrowInfo.getBorrowUserId(), repayMoney,
						base, repaymentPlan.getRepayInterestMoney(), TransType.REPAYMENT, TradeMode.SUBTRACT,
						borrowInfo.getId().toString(), "融资还款|标的:" + borrowInfo.getBorrowName());
			}
		}
		/**
		 * 判断本期还款计划对应的收款计划是否已经都还清,如果都还清则更新本期还款计划状态为：已还清。
		 */
		boolean isRepaymentPlanRepaymented = serviceFactory.getRepaymentService().checkRepaymentPlanIsRepaymented(Long.parseLong(proId), curRecNum);
		if (isRepaymentPlanRepaymented) {
			serviceFactory.getDaoFactory().getRepaymentPlanDao().updateStatus(Long.parseLong(proId), ReplaymentStatus.REPAYMENTED,
					ReplaymentStatus.SETTLING, new Date(), new Date(), curRecNum);
		}
		/**
		 * 判断借款人的所有还款计划是否已经全部还清，若已经全部还清则更新借款标的状态为：已还清。
		 */
		boolean isBorrowInfoRepaymented = serviceFactory.getRepaymentService().checkBorrowInfoIsRepaymented(Long.parseLong(proId));
		if (isBorrowInfoRepaymented) {
			//更新标的状态为已还清
			serviceFactory.getDaoFactory().getBorrowInfoDao().updateStatus(Long.parseLong(proId), BorrowStatus.REPAYMENTED, BorrowStatus.REPAYMENTING,new Date(),new Date());
			//同时将该借款标的对应的投资信息记录状态改变为：已回款
			serviceFactory.getDaoFactory().getInvestInfoDao().updateAllStatus(borrowInfo.getId(),InvestStatus.LOANED,InvestStatus.RETURNED);
		}
		/**
		 * 如果是平台垫资还款则添加追偿信息
		 */
		if (MSConstants.CHAR_ONE.equals(response.getMerPriv())) {
			if (repayMoney > 0) {
				saveRecoverRepayInfo(repaymentPlan, repayMoney, repaymentPlan.getRepayBaseMoney(), repaymentPlan.getRepayInterestMoney());
			}
		}
		return ServiceResultFactory.getServiceResult(CommonCode.TRANS_SUC, String.class);
	}
	/**
	 * 保存垫资信息
	 * @param plan
	 * @param repaymoney
	 * @param totalRepayBaseMoney
	 * @param interest
	 */
	private void saveRecoverRepayInfo(RepaymentPlan plan, Long repaymoney, Long totalRepayBaseMoney, Long interest) {
		RecoverRepay recoverRepay = new RecoverRepay();
		recoverRepay.setRepaymentPlanId(plan.getId());
		recoverRepay.setStatus(RecoverRepay.RecoverRepayStatus.UNRECOVER);
		recoverRepay.setCreateTime(new Date());
		recoverRepay.setUpdateTime(new Date());
		recoverRepay.setRecoverRepayMoney(repaymoney);
		recoverRepay.setRecoverRepayBaseMoney(totalRepayBaseMoney);
		recoverRepay.setRecoverRepayInterestMoney(interest);
		recoverRepay.setRepaymentPlanId(plan.getId());
		recoverRepay.setBorrowInfoId(plan.getBorrowInfoId());
		recoverRepay.setBorrowName(plan.getBorrowName());
		recoverRepay.setBorrowUserName(plan.getBorrowUserName());
		recoverRepay.setTotalRepayNum(plan.getTotalRepayNum());
		recoverRepay.setCurRepayNum(plan.getCurRepayNum());
		recoverRepay.setLastRepayDate(plan.getLastRepayDate());
		recoverRepay.setOverduePenalty(plan.getOverduePenalty());
		recoverRepay.setOverdueDate(plan.getOverdueDate());
//		recoverRepay.setRepayTime(plan.getRepayTime());
		recoverRepay.setBorrowUserId(plan.getBorrowUserId());
		recoverRepay.setIsOverDured(plan.getIsOverDured());
		serviceFactory.getPersistService().save(recoverRepay);
	}

	@Override
	public ServiceResult<String> dealRepaymentResult(RepaymentResponseMsg response) {
		ServiceResult<String> result = new ServiceResult<String>();
		if (response == null) {
			result.setIsSuccess(false);
			result.setCode(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRCODE_UNKOWN);
			result.setMessage(RespCodeConstants.CommonCode.TRANSMESSAGE_ERRMSG_NORETURNMSG);
			return result;
		}
		if (!CommonCode.TRANS_SUC.equals(response.getRespCode())) {
			result.setIsSuccess(false);
			result.setCode(response.getRespCode());
			result.setMessage(response.getRespDesc());
			return result;
		}
		if ("recoverRepayment".equals(response.getMerPriv())) {// 偿还垫资操作
			RecoverRepay recover = serviceFactory.getPersistService().get(RecoverRepay.class,Long.parseLong(response.getOrdId()));
			if (recover == null || !recover.getStatus().equals(RecoverRepayStatus.RECOVERING)) {
				result.setIsSuccess(false);
				result.setCode(RespCodeConstants.RepaymentCode.REPAYMENT_NOTFOUND_RECOVER);
				result.setMessage(RespCodeConstants.RepaymentCode.REPAYMENT_NOTFOUND_RECOVER_MSG);
				return result;
			}
			if (recover.getRecoverRepayMoney() != MoneyUtil.convertLongYuanToFen(Double.parseDouble(response.getTransAmt()))) {
				result.setIsSuccess(false);
				result.setCode(RespCodeConstants.RepaymentCode.REPAYMENT_BACKMONEYERROR);
				result.setMessage(RespCodeConstants.RepaymentCode.REPAYMENT_BACKMONEYERROR_MSG);
				return result;
			}
			int i = serviceFactory.getDaoFactory().getRecoverRepayDao().updateStatus(Long.parseLong(response.getOrdId()), RecoverRepayStatus.RECOVERED, RecoverRepayStatus.RECOVERING, new Date(), new Date());
			if (i > 0) {
				serviceFactory.getAccountService().changeAccountMoney(recover.getBorrowUserId(),
						recover.getRecoverRepayMoney(), recover.getRecoverRepayBaseMoney(),
						recover.getRecoverRepayInterestMoney(), TransType.PAYBACK, TradeMode.SUBTRACT,
						recover.getId().toString(),
						"借款人:" + recover.getBorrowUserName() + "偿还垫资本息|标的:" + recover.getBorrowName());

				BorrowInfo borrowInfo = serviceFactory.getPersistService().get(BorrowInfo.class, recover.getBorrowInfoId());

				serviceFactory.getAccountService().add(borrowInfo.getGuaranteeUserId(), TransType.PAYBACK,
						recover.getRecoverRepayMoney(), recover.getId().toString(),
						"担保企业" + borrowInfo.getGuaranteeRealName() + "回收垫资本息|标的：" + recover.getBorrowName());

				result.setIsSuccess(true);
				result.setCode(RespCodeConstants.CommonCode.TRANS_SUC);
				result.setMessage(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
			}
		} else if ("repayment".equals(response.getMerPriv())) {//还款对账中会用到这段代码
			ReceivePlan receivePlan = serviceFactory.getPersistService().get(ReceivePlan.class,Long.parseLong(response.getOrdId()));
			BorrowInfo borrowInfo = serviceFactory.getPersistService().get(BorrowInfo.class,receivePlan.getBorrowInfoId());
			if (borrowInfo == null || !borrowInfo.getStatus().equals(BorrowStatus.REPAYMENTING)) {
				result.setIsSuccess(false);
				result.setCode(RespCodeConstants.BorrowInfoCode.BORROWINFO_UNKONW);
				result.setMessage(RespCodeConstants.BorrowInfoCode.BORROWINFO_UNKONW_MSG);
				return result;
			}
			if (receivePlan == null || !receivePlan.getStatus().equals(ReceiveStatus.RECEIVING)) {
				result.setIsSuccess(false);
				result.setCode(RespCodeConstants.RepaymentCode.REPAYMENT_NOTFOUND_RECOVER);
				result.setMessage(RespCodeConstants.RepaymentCode.REPAYMENT_NOTFOUND_RECOVER_MSG);
				return result;
			}
			if (receivePlan.getRecMoney() != MoneyUtil.convertLongYuanToFen(Double.parseDouble(response.getTransAmt()))) {
				result.setIsSuccess(false);
				result.setCode(RespCodeConstants.RepaymentCode.REPAYMENT_BACKMONEYERROR);
				result.setMessage(RespCodeConstants.RepaymentCode.REPAYMENT_BACKMONEYERROR_MSG);
				return result;
			}
			receivePlan.setStatus(ReceiveStatus.RECEIVED);// 更新对应的收款计划中收款状态为：已收款
			receivePlan.setReceiveTime(new Date());
			receivePlan.setUpdateTime(new Date());
			serviceFactory.getPersistService().update(receivePlan);

			// 收款人资金账户变动,资金流水添加
			serviceFactory.getAccountService().changeAccountMoney(receivePlan.getInvestUserId(),
					receivePlan.getRecBaseMoney(), receivePlan.getRecBaseMoney(), 0L, TransType.REPAYMENT,
					TradeMode.ADD, receivePlan.getId().toString(), "收回本金 | 投资：" + borrowInfo.getBorrowName());

			// 收款人资金账户变动,资金流水添加 回收利息
			serviceFactory.getAccountService().changeAccountMoney(receivePlan.getInvestUserId(),
					receivePlan.getRecInterestMoney(), 0L, receivePlan.getRecInterestMoney(), TransType.REPAYMENT,
					TradeMode.ADD, receivePlan.getId().toString(), "收回利息 | 投资：" + borrowInfo.getBorrowName());

			// 资金流水添加,附加利息
			if (receivePlan.getRecAddMoney() > 0) {
				serviceFactory.getAccountService().changeAccountMoney(receivePlan.getInvestUserId(),
						receivePlan.getRecAddMoney(), 0L, receivePlan.getRecAddMoney(), TransType.ADDMONEY,
						TradeMode.ADD, receivePlan.getId().toString(), "收回附加利息 | 投资：" + borrowInfo.getBorrowName());
			}
			Long repayMoney = receivePlan.getRecBaseMoney() + receivePlan.getRecInterestMoney();
			// 还款人资金账户变动,资金流水添加 根据实际出账账户和借款人账户是否相同来判断是否是垫资还款交易
			if (!borrowInfo.getBorrowUserTrustAccountId().equals(response.getOutCustId())) {
				// 担保公司垫资还款,记录担保用户账户资金变动
				serviceFactory.getAccountService().changeAccountMoney(borrowInfo.getGuaranteeUserId(), repayMoney,
						TransType.ADVANCEREPAY, TradeMode.SUBTRACT, borrowInfo.getId().toString(),
						"担保人垫资本息| 标的:" + borrowInfo.getBorrowName() + ",第" + receivePlan.getCurRecNum() + "期还款");
			} else {
				// 借款人正常还款
				serviceFactory.getAccountService().changeAccountMoney(borrowInfo.getBorrowUserId(), repayMoney,
						receivePlan.getRecBaseMoney(), receivePlan.getRecInterestMoney(), TransType.REPAYMENT,
						TradeMode.SUBTRACT, borrowInfo.getId().toString(), "融资还款|标的:" + borrowInfo.getBorrowName());
			}

			// 判断本期还款计划对应的收款计划是否已经都还清,如果都还清则更新本期还款计划状态为：已还清。
			long count = daoFactory.getReceivePlanDao().countPlans(borrowInfo.getId(), null,
					receivePlan.getCurRecNum(), new ReceiveStatus[] { ReceiveStatus.WAITREC, ReceiveStatus.RECEIVING });
			List<RepaymentPlan> repayPlans = daoFactory.getRepaymentPlanDao().lockList(borrowInfo.getId(),
					receivePlan.getCurRecNum(),
					new ReplaymentStatus[] { ReplaymentStatus.SETTLING, ReplaymentStatus.UNSETTLE });
			if (count == 0 && repayPlans != null && repayPlans.size() > 0) {
				RepaymentPlan repaymentPlan = repayPlans.get(0);
				repaymentPlan.setStatus(RepaymentPlan.ReplaymentStatus.REPAYMENTED);
				repaymentPlan.setRepayTime(new Date());
				repaymentPlan.setUpdateTime(new Date());
				serviceFactory.getPersistService().update(repaymentPlan);
			}
			// 判断借款人的所有还款计划是否已经全部还清，若已经全部还清则更新借款标的状态为：已还清。
			ReplaymentStatus[] status = new ReplaymentStatus[] { ReplaymentStatus.UNSETTLE, ReplaymentStatus.SETTLING };
			long repayCount = daoFactory.getRepaymentPlanDao().countRepayPlan(borrowInfo.getId(), status);
			final Long borrowId = borrowInfo.getId();
			if (repayCount == 0) {
				execute.execute(new Runnable() {
					public void run() {
						BorrowInfo borrow = daoFactory.getBorrowInfoDao().lockById(borrowId);
						borrow.setStatus(BorrowStatus.REPAYMENTED);
						borrow.setRepaymentedTime(new Date());
						borrow.setUpdateTime(new Date());
						daoFactory.getBorrowInfoDao().update(borrow);

						List<InvestInfo> infos = daoFactory.getInvestInfoDao().lockList(borrow.getId(),new InvestStatus[] { InvestStatus.LOANED });
						for (InvestInfo info : infos) {
							info.setStatus(InvestStatus.RETURNED);
						}
						daoFactory.getInvestInfoDao().updateAll(infos);
					}
				});
			}
		}
		return result;
	}

	@Override
	public void packBatchRepayment(RepaymentRequestMsg reqMsg) {
		RepaymentPlan repaymentPlan = serviceFactory.getPersistService().get(RepaymentPlan.class, Long.parseLong(reqMsg.getRepaymentPlanId()));
		repaymentPlan.setStatus(ReplaymentStatus.SETTLING);
		if (reqMsg.isPlatfor()) {
			repaymentPlan.setType(ReplaymentType.ADVANCE);
		} else {
			repaymentPlan.setType(ReplaymentType.NORMAL);
		}
		serviceFactory.getPersistService().update(repaymentPlan);
		serviceFactory.getRepaymentService().setReceivePlanBatch(reqMsg.getReceivePlanIds(), reqMsg.getBatchId());
	}

	@Override
	public void setReceivePlanBatch(List<Long> receivePlanIds, String batchId) {
		for (Long id : receivePlanIds) {
			ReceivePlan plan = daoFactory.getReceivePlanDao().get(id);
			plan.setBatchId(batchId);
			plan.setStatus(ReceiveStatus.RECEIVING);
			daoFactory.getReceivePlanDao().update(plan);
		}
	}

	@Override
	public void packRepayment(RepaymentRequestMsg reqMsg) {
		if ("recoverRepayment".equals(reqMsg.getMerPriv())) {
			// 借款人偿还垫资操作
			RecoverRepay recover = serviceFactory.getPersistService().get(RecoverRepay.class,Long.parseLong(reqMsg.getOrdId()));
			recover.setStatus(RecoverRepayStatus.RECOVERING);
			// 设置订单日期
			reqMsg.setOrdDate(DateTimeUtil.formatToStr(recover.getCreateTime(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			List<InvestInfo> investInfos = daoFactory.getInvestInfoDao().queryList(reqMsg.getBorrowinfoId(), null);
			InvestInfo investInfo = investInfos.get(0);
			// 设置关联投标id
			reqMsg.setSubOrdId(investInfo.getId().toString());
			reqMsg.setSubOrdDate(DateTimeUtil.formatToStr(investInfo.getCreateTime(), DateTimeUtil.DATE_FORMAT_YYYYMMDD));
			// 设置入款子账户
			Account account = serviceFactory.getAccountService().getAccount(reqMsg.getGuaranteeUserId());
			reqMsg.setInAcctId("");
			if (account != null) {
				reqMsg.setInAcctId(account.getSubAccountId());
			}
			serviceFactory.getPersistService().update(recover);
		}
	}

	@Override
	public void repaymentReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate)
	{
		ReconciliationResponseMsg response = serviceFactory.getRepaymentService().doRepaymentReconciliation(pageNum,
				pageSize, beginDate, endDate);
		if (!StringHelper.isEmpty(response.getTotalItems())
				&& (pageNum * pageSize) < Integer.parseInt(response.getTotalItems()))
		{
			repaymentReconciliation(pageNum + 1, pageSize, beginDate, endDate);
		}
	}

	@Override
	public ReconciliationResponseMsg doRepaymentReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
			Date endDate)
	{
		ReconciliationRequestMsg reqMsg = new ReconciliationRequestMsg();
		reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setPageNum(pageNum.toString());
		reqMsg.setPageSize(pageSize.toString());
		reqMsg.setQueryTransType("REPAYMENT");
		reqMsg.setPartnerTransType(PartnerTransType.Reconciliation);
		reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
		ReconciliationResponseMsg response = (ReconciliationResponseMsg) serviceFactory.getPartnerService().request(
				reqMsg);
		List<ReconciliationInfo> list = response.getReconciliationDtoList();
		if (list != null && list.size() > 0)
		{
			PoolServer poolServer = new PoolServer(50);
			for (ReconciliationInfo dto : list)
			{
				final RepaymentResponseMsg repaymentResponseMsg = new RepaymentResponseMsg();
				repaymentResponseMsg.setOrdId(dto.getOrdId());
				repaymentResponseMsg.setTransAmt(dto.getTransAmt());
				repaymentResponseMsg.setOutCustId(dto.getBorrCustId());
				if ("I".equals(dto.getTransStat()))
				{// 失败
					repaymentResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
					repaymentResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
				}
				else if ("P".equals(dto.getTransStat()))
				{// 成功
					repaymentResponseMsg.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
					repaymentResponseMsg.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
				}
				RecoverRepay recoverRepay = serviceFactory.getPersistService().get(RecoverRepay.class,
						Long.parseLong(dto.getOrdId()));
				if (recoverRepay != null)
				{
					repaymentResponseMsg.setMerPriv("recoverRepayment");// 还垫资交易
				}
				else
				{
					repaymentResponseMsg.setMerPriv("repayment");// 正常还款交易
				}
				poolServer.executeTask(new Runnable()
				{
					public void run()
					{
						serviceFactory.getRepaymentService().dealRepaymentResult(repaymentResponseMsg);
					}
				});
			}
			poolServer.endServer();
		}
		return response;
	}

	@Override
	public void trfReconciliation(Integer pageNum, Integer pageSize, Date beginDate, Date endDate)
	{
		TrfReconciliationResponseMsg response = serviceFactory.getRepaymentService().doTrfReconciliation(pageNum,
				pageSize, beginDate, endDate);
		if (!StringHelper.isEmpty(response.getTotalItems())
				&& (pageNum * pageSize) < Integer.parseInt(response.getTotalItems()))
		{
			trfReconciliation(pageNum + 1, pageSize, beginDate, endDate);
		}
	}

	@Override
	public TrfReconciliationResponseMsg doTrfReconciliation(Integer pageNum, Integer pageSize, Date beginDate,
			Date endDate)
	{
		TrfReconciliationRequestMsg reqMsg = new TrfReconciliationRequestMsg();
		reqMsg.setBeginDate(DateTimeUtil.formatToStr(beginDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setEndDate(DateTimeUtil.formatToStr(endDate, DateTimeUtil.DATE_FORMAT_YYYYMMDD));
		reqMsg.setPageNum(pageNum.toString());
		reqMsg.setPageSize(pageSize.toString());

		reqMsg.setPartnerTransType(PartnerTransType.TrfReconciliation);
		reqMsg.setTransType(TransCodeConstants.PartnerTransCode.REQUEST);
		TrfReconciliationResponseMsg response = (TrfReconciliationResponseMsg) serviceFactory.getPartnerService()
				.request(reqMsg);
		List<TrfReconciliationDto> list = response.getTrfReconciliationDtoList();
		if (list != null && list.size() > 0)
		{
			PoolServer poolServer = new PoolServer(list.size());
			for (TrfReconciliationDto dto : list)
			{
				if ("S".equals(dto.getTransStat()) || "F".equals(dto.getTransStat()))
				{
					final TransferResponse transferResponse = new TransferResponse();
					transferResponse.setOrdId(dto.getOrdId());
					if ("S".equals(dto.getTransStat()))
					{// 成功
						transferResponse.setRespCode(RespCodeConstants.CommonCode.TRANS_SUC);
						transferResponse.setRespDesc(RespCodeConstants.CommonCode.TRANS_SUC_MSG);
					}
					else if ("F".equals(dto.getTransStat()))
					{// 失败
						transferResponse.setRespCode(RespCodeConstants.CommonCode.TRANS_FAIL);
						transferResponse.setRespDesc(RespCodeConstants.CommonCode.TRANS_FAIL_MSG);
					}
					poolServer.executeTask(new Runnable()
					{
						public void run()
						{
							serviceFactory.getTransferService().dealTransferResult(transferResponse);
						}
					});
				}
			}
			poolServer.endServer();
		}
		return response;
	}
}
